part of internal;

class Cursor {
   Position _pos;
   DoublyLinkedList<Line> _rend;

   // generator
   Cursor (DoublyLinkedList<Line> rend) {
      _rend = rend;
   }

   // mutators
   void init (Buffer buf, Position pos) {
      if (dev) {
         if (pos.ln >= buf.lc) throw new ArgumentError(pos);
         if (pos.ch > buf.nth(pos.ln).length) throw new ArgumentError(pos);
      }
      _pos = new Position(pos.ln, pos.ch);
      _rend.nth(_pos.ln).curOn(_pos.ch);
   }
   void kill () {
      _rend.nth(_pos.ln).curOff();
      _pos = null;
   }

   void left (Buffer buf) {
      if (_pos.ln == 0 && _pos.ch == 0) return;
      _rend.nth(_pos.ln).curOff();
      if (_pos.ch == 0) {
         _pos.ln--;
         _pos.ch = buf.nth(_pos.ln).length;
      }
      else _pos.ch--;
      _rend.nth(_pos.ln).curOn(_pos.ch);
   }
   void right (Buffer buf) {
      if (_pos.ln == buf.lc - 1 && _pos.ch == buf.nth(_pos.ln).length) return;
      _rend.nth(_pos.ln).curOff();
      if (_pos.ch == buf.nth(_pos.ln).length) {
         _pos.ln++;
         _pos.ch = 0;
      }
      else _pos.ch++;
      _rend.nth(_pos.ln).curOn(_pos.ch);
   }
   void up (Buffer buf, int far) {
      if (_pos.ln == 0) return;
      _rend.nth(_pos.ln).curOff();
      _pos.ln--;
      int temp = buf.nth(_pos.ln).length;
      if (temp > far) _pos.ch = far;
      else _pos.ch = temp;
      _rend.nth(_pos.ln).curOn(_pos.ch);
   }
   void down (Buffer buf, int far) {
      if (_pos.ln == buf.lc - 1) return;
      _rend.nth(_pos.ln).curOff();
      _pos.ln++;
      int temp = buf.nth(_pos.ln).length;
      if (temp > far) _pos.ch = far;
      else _pos.ch = temp;
      _rend.nth(_pos.ln).curOn(_pos.ch);
   }
   /*
   void set pos (Buffer buf, Position pos) {
      if (dev) {
         if (pos.ln >= buf.lc) argErr(pos);
         if (pos.ch > buf.nth(pos.ln).length) argErr(pos);
      }
      _rend.nth(_pos.ln).curOff();
      _pos.ln = pos.ln;
      _pos.ch = pos.ch;
      _rend.nth(_pos.ln).curOn(_pos.ch);
   }
   */

   // observers
   Position get pos => new Position(_pos.ln, _pos.ch);
   bool get active => _pos != null;
/*
   // invariants
   bool get valid {
      if (_pos == null) return false;
      if (_buf == null) return false;
      if (_stick == null) return false;
      if (_pos.ln >= _buf.lc) return false;
      if (_pos.ch > _buf.nth(_pos.ln).length) return false;
      String top = _stick.style.top;
      String left = _stick.style.left;
      if (!top.endsWith('em')) return false;
      if (!left.endsWith('em')) return false;
      if (int.parse(top.substring(0, top.length - 2)) != _pos.ln) return false;
      if (double.parse(left.substring(0, left.length - 2)) != _pos.ch / 2.0) return false;
      return true;
   }

   // printing
   String toString () => 'pos -> $_pos\nstick -> $_stick';
*/
}
